/**
 * 
 */
package com.dfhc.pub.concurrencycontrol;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author longsebo
 * 请求并发锁,用来控制防止重复提交，替换文件加锁（并发量非常高情况，依然有问题)
 */
public class RequestConcurrentLock {
//	private static RequestConcurrentLock requestConcurrentLock;
	//guid列表锁（公平锁)
	private ReentrantLock queueLock = new ReentrantLock(true);
	/**
	 * guid列表
	 */
	private List<String> guidList = new ArrayList<String>();
//	/**
//	 * 获取单例
//	 * @return
//	 */
//	public static synchronized RequestConcurrentLock getSingleton(){
//		if(requestConcurrentLock==null){
//			requestConcurrentLock = new RequestConcurrentLock();
//		}
//		return requestConcurrentLock;
//	}
	public RequestConcurrentLock(){
		
	}
	/**
	 * 根据guid加锁,如果guidList存在这个guid，则报错
	 * @param guid
	 * @return
	 */
	public boolean lock(String guid){
		try{
			queueLock.lock();
			if(guidList.contains(guid)){
				throw new RequestConcurrentLockException("请勿重复提交或别人在操作!");
			}
			//加入guidList
			guidList.add(guid);
			return true;
		}finally{
			queueLock.unlock();
		}
	}
	/**
	 * 根据guid解锁，从guidList删除guid
	 * @param guid
	 */
	public void unLock(String guid){
		try{
			queueLock.lock();
			if(guidList.contains(guid)){
				//从guidList删除
				guidList.remove(guid);
			}
		}finally{
			queueLock.unlock();
			synchronized (guidList) {
				guidList.notifyAll();
			}
		}
	}
	/**
	 * 根据guid加锁,如果guidList存在这个guid，则等待指定时间，如果超时后guidList还存在这个guid，则加锁失败	
	 * @param guid
	 * @param waitTime
	 * @return
	 */
	public boolean lock(String guid, long waitTime) {
		boolean isUnLock = false;
		try{			
			long begintime;
			long endtime;
			queueLock.lock();
			isUnLock =false;
			begintime = System.currentTimeMillis();
			while(guidList.contains(guid)){
				queueLock.unlock();
				isUnLock =true;
				synchronized (guidList) {
					guidList.wait(100);					
					queueLock.lock();					
					isUnLock = false;
					endtime = System.currentTimeMillis();
					if(endtime - begintime>=waitTime){
						throw new RequestConcurrentLockException("等待加锁超时!");
					}
				}
			}
			//加入guidList
			guidList.add(guid);
			return true;
		}catch(RequestConcurrentLockException e){
			throw e;
		}catch(Exception e){
			throw new RequestConcurrentLockException(e);
		}finally{
			if(!isUnLock){
				queueLock.unlock();
			}
		}
	}
}
